package edu.geo.service;

import java.io.Serializable;
import java.util.List;

import edu.geo.containers.geom.impl.LineSegment;
import edu.geo.containers.geom.impl.Point;
import edu.geo.containers.geom.impl.Polygon;
import edu.geo.containers.geomdomain.GeometricDomain;
import edu.geo.containers.geomdomain.GeometricDomainFault;
import edu.geo.containers.geomdomain.Grid;
import edu.geo.exception.GeoInfoException;
import edu.geo.spaghetti.SpaghettiRepresentation;

/**
 * Define las firmas de los métodos que permiten crear, eliminar, modificar y
 * validar un dominio geométrico.
 * 
 * @author alejandro.sanchez
 * 
 */
public interface IGeometricDomainServiceFacade extends Serializable {

	/**
	 * Permite crear un dominio geométrico y almacenar sus atributos en la base
	 * de datos.
	 * 
	 * @param geomDomain
	 *            Una referencia a un objeto de tipo
	 *            <code>GeometricDomain</code> que almacena la especificación
	 *            del dominio geométrico.
	 * @see edu.geo.containers.geomdomain.GeometricDomain
	 * 
	 * @return Un <code>entero</code> que representa el identificador único del
	 *         dominio geométrico en la base de datos.
	 * 
	 * @throws GeoInfoException
	 *             en caso que ocurra una excepción durante la creación del
	 *             dominio geométrico.
	 */
	public int save(GeometricDomain geomDomain) throws GeoInfoException;

	/**
	 * Permite la eliminación de un dominio geométrico de la base de datos.
	 * 
	 * @param geomDomainId
	 *            Un <code>entero</code> que representa el identificador único
	 *            del dominio geométrico en la base de datos.
	 * 
	 * @throws GeoInfoException
	 *             en caso que ocurra una excepción durante la eliminación del
	 *             dominio geométrico.
	 */
	public void delete(int geomDomainId) throws GeoInfoException;

	/**
	 * Adiciona un punto a un dominio geométrico existente en la base de datos.
	 * 
	 * @param geomDomainId
	 *            Un <code>entero</code> que representa el identificador único
	 *            del dominio geométrico en la base de datos.
	 * @param point
	 *            Objeto de tipo <code>Point</code> que desea agregarse al
	 *            diminio geométrico.
	 * @see edu.geo.containers.geom.impl.Point
	 * @throws GeoInfoException
	 *             en caso que ocurra una excepción durante la adición del punto
	 *             al dominio geométrico.
	 */
	public void addPoint(int geomDomainId, Point point) throws GeoInfoException;

	/**
	 * Adiciona un segmento de línea a un dominio geométrico existente.
	 * 
	 * @param geomDomainId
	 *            Un <code>entero</code> que representa el identificador único
	 *            del dominio geométrico en la base de datos.
	 * @param lineSegment
	 *            Objeto de tipo <code>LineSegment</code> que desea agregarse al
	 *            diminio geométrico.
	 * @see edu.geo.containers.geom.impl.LineSegment
	 * @throws GeoInfoException
	 *             en caso que ocurra una excepción durante la adición del
	 *             segmento de línea al dominio geométrico.
	 */
	public void addLineSegment(int geomDomainId, LineSegment lineSegment)
			throws GeoInfoException;

	/**
	 * Elimina un punto de un dominio geométrico existente.
	 * 
	 * @param geomDomainId
	 *            Un <code>entero</code> que representa el identificador único
	 *            del dominio geométrico en la base de datos
	 * @param point
	 *            point Objeto de tipo <code>Point</code> que desea eliminarse
	 *            del diminio geométrico.
	 * @see edu.geo.containers.geom.impl.Point
	 * 
	 * @throws GeoInfoException
	 *             en caso que ocurra una excepción durante la eliminación del
	 *             punto del dominio geométrico.
	 */
	public void deletePoint(int geomDomainId, Point point)
			throws GeoInfoException;

	/**
	 * Elimina un segmento de línea de un dominio geométrico existente.
	 * 
	 * @param geomDomainId
	 *            Un <code>entero</code> que representa el identificador único
	 *            del dominio geométrico en la base de datos.
	 * @param lineSegment
	 *            Objeto de tipo <code>LineSegment</code> que desea eliminarse
	 *            del diminio geométrico.
	 * @see edu.geo.containers.geom.impl.LineSegment
	 * 
	 * @throws GeoInfoException
	 *             GeoInfoException en caso que ocurra una excepción durante la
	 *             eliminación del segmento de línea del dominio geométrico.
	 */
	public void deleteLineSegment(int geomDomainId, LineSegment lineSegment)
			throws GeoInfoException;

	/**
	 * Valida el dominio geométrico existente, verificando las condiciones que
	 * deben cumplirse para ser un dominio geométrico válido. Si la lista de
	 * faltas retornada es vacía, quiere decir que es un dominio geométrico
	 * válido, en caso contrario, es un dominio geométrico invalido.
	 * 
	 * @param geomDomain
	 *            Una referencia a un objeto de tipo
	 *            <code>GeometricDomain</code> que almacena la especificación
	 *            del dominio geométrico.
	 * @see edu.geo.containers.geomdomain.GeometricDomain
	 * 
	 * @return Una lista con las condiciones que se incumplen para que no sea un
	 *         dominio geométrico.
	 * @see edu.geo.containers.geomdomain.GeometricDomainFault
	 * 
	 * @throws GeoInfoException
	 *             Una excepción en caso que el dominio no pueda ser validado.
	 */
	public List<GeometricDomainFault> validate(GeometricDomain geomDomain)
			throws GeoInfoException;
	
	
	/**
	 * Valida el dominio geométrico existente, verificando las condiciones que
	 * deben cumplirse para ser un dominio geométrico válido. Si la lista de
	 * faltas retornada es vacía, quiere decir que es un dominio geométrico
	 * válido, en caso contrario, es un dominio geométrico invalido.
	 * 
	 * @param geomDomainId
	 *            Identificador del dominio que se va a validar.
	 * @see edu.geo.containers.geomdomain.GeometricDomain
	 * 
	 * @return Una lista con las condiciones que se incumplen para que no sea un
	 *         dominio geométrico.
	 * @see edu.geo.containers.geomdomain.GeometricDomainFault
	 * 
	 * @throws GeoInfoException
	 *             Una excepción en caso que el dominio no pueda ser validado.
	 */
	public List<GeometricDomainFault> validate(int geomDomainId)
			throws GeoInfoException;

	/**
	 * Ajusta un dominio geométrico para que cumpla las condiciones que
	 * establecen un dominio geométrico válido. En caso que desee almacenarse el
	 * dominio geométrico en la base de datos, el parámetro store deber tener el
	 * valor verdadero(true), de lo contrario, el dominio geométrico ajustado no
	 * se almacenará en la base de datos.
	 * 
	 * @see #validate(GeometricDomain)
	 * 
	 * @param geomDomain
	 *            Una referencia a un objeto de tipo
	 *            <code>GeometricDomain</code> que almacena la especificación
	 *            del dominio geométrico.
	 * @see edu.geo.containers.geomdomain.GeometricDomain
	 * @param store
	 *            <code>booleano</code> con valor verdadero(true) en caso que se
	 *            desee almacenar el dominio geométrico ajustado, falso (false)
	 *            en caso que no se desee guardar.
	 * @return El dominio geométrico ajustado. En este caso se utiliza el
	 *         algoritmo de Green-Yao para ajustar el domimio geométrico y de
	 *         esa manera cumplir con las c condiciones necesarias para ser un
	 *         dominio válido.
	 * 
	 * @throws GeoInfoException
	 *             En caso que ocurra una excepción durante el ajuste del
	 *             dominio geométrico.
	 */
	public GeometricDomain adjust(GeometricDomain geomDomain, boolean store)
			throws GeoInfoException;

	/**
	 * Obtiene todos los dominios geométricos almacenados en la base de datos,
	 * tanto los válidos (ajustados y/o que cumplen todas las condiciones que
	 * establecen un dominio geométrico válido) como los invalidos (aquellos que
	 * no han sido ajustados.
	 * 
	 * @return Lista de domimios geométricos almacenados en la base de datos.
	 * @see edu.geo.containers.geomdomain.GeometricDomain
	 * 
	 * @throws GeoInfoException
	 *             En caso que ocurra una excepción durante la consulta de los
	 *             dominios geométricos.
	 */
	public List<GeometricDomain> retrieveAll() throws GeoInfoException;

	/**
	 * Obtiene el dominio geométrico cuyo identificador es el valor pasado como
	 * argumento de la función.
	 * 
	 * @param id
	 *            Un <code>entero</code> que representa el identificador del
	 *            dominio geométrico que se quiere recuperar.
	 * 
	 * @return El dominio geométrico con el identificador especificado.
	 * @see edu.geo.containers.geomdomain.GeometricDomain
	 * 
	 * @throws GeoInfoException
	 *             En caso que ocurra una excepción durante la consulta del
	 *             dominio geométrico.
	 */
	public GeometricDomain retrieve(int id) throws GeoInfoException;

	/**
	 * Verifica la existencia de un punto (por geometría) en la base de datos.
	 * En caso que exista, retornará el id asociado al punto, en caso que no,
	 * retornara el valor -1.
	 * 
	 * @param point
	 *            Un objeto de tipo punto.
	 * @see edu.geo.containers.geom.impl.point
	 * @return El id del punto en caso que exista en la base de datos, en otro
	 *         caso retornará -1.
	 * 
	 * @throws GeoInfoException
	 *             Si ocurre un error durante la verificación de la existencia
	 *             de un punto.
	 */
	public int verifyPointExistence(Point point) throws GeoInfoException;

	/**
	 * 
	 * @param lineSegment
	 *            Segmento de línea para el que se verificará su existencia
	 *            (existencia verificada por gemetría únicamente).
	 * @return El id del segmento de línea en caso de que exista, en otro caso
	 *         -1.
	 * @throws GeoInfoException
	 *             Si ocurre algún error en la verificación de la existencia del
	 *             segmento de línea.
	 */
	public int verifyLineSegmentExistence(LineSegment lineSegment)
			throws GeoInfoException;
	
	/**
	 * Actualiza el dominio geométrico con los segmentos y líneas que el usuario
	 * haya modificado (adicionado, eliminado)/
	 * @param geomDomainId Id del dominio geométrico a agregar.
	 * @param points Lista de puntos del dominio geométrico.
	 * @param lineSegments Lista de segmentos de línea del dominio geométrico.
	 * @return
	 * @throws GeoInfoException En caso que ocurra un error en la modificación del
	 *         dominio geométrico.
	 */
	public boolean modifyGeometriesDomain(int geomDomainId, List<Point> points,
			List<LineSegment> lineSegments) throws GeoInfoException;
	
	/**
	 * Obtiene la retícula del dominio geométrico especificado. 
	 * @param geomDomainId Id de un dominio geométrico.
	 * @return La grilla del dominio geométrico con el identificador recibido como parámetro.
	 * @throws GeoInfoException En caso que se presente una excepción en la recuperación de una grilla.
	 */
	public Grid retrieveGridGeomDomain(int geomDomainId) throws GeoInfoException;
	
	/**
	 * Elimina un punto o línea del dominio geométrico.
	 * @param geomDomainId Id de un dominio existente
	 * @param featureId Id de un objeto punto o segmento de línea existente
	 * @throws GeoInfoException 
	 */
	public void deleteFeature(int geomDomainId, int featureId) throws GeoInfoException;

	/**
	 * Permite representar un dominio geométrico mediante el modelo espacial de Spaghetti
	 * @param geometricDomain
	 * @return Un objeto con la representación espacial tipo Spaghetti.
	 */
	SpaghettiRepresentation asSpaghettiRepresentation(GeometricDomain geometricDomain);
			

}
